<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
    // <!-- 此处请编写 Event 方法 -->
    class Event {
      constructor() {
        this.events = {};
      }
      on (type, listener, params) {
        // 因为其他的类可能继承自EventEmitter，子类的events可能为空，保证子类必须存在此实例属性
        if (!this.events) {
          this.events = {};
        }
        if (this.events[type]) {
          if (params) {
            this.events[type].unshift(listener);
          } else {
            this.events[type].push(listener);
          }
        } else {
          this.events[type] = [listener]
        }

        if (type !== 'newListener') {
          // node的EventEmitter模块自带的特殊事件，该事件在添加新事件监听器的时候触发
          this.emit('newListener', type);
        }
      }
      emit (type, ...args) {
        if (this.events[type]) {
          this.events[type].forEach(fn => fn.call(this, ...args));
        }
      }
      // 只绑定一次，然后解绑
      once (type, listener) {
        const self = this;
        function one (...args) {
          listener.call(this, ...args);
          self.off(type, one);
        }
        self.on(type, one)
      }
      off (type, listener) {
        if (this.events[type]) {
          const index = this.events[type].indexOf(listener);
          this.events[type].splice(index, 1);
        }
      }
    }

    // <!-- 运行函数 -->
    const myEvent = new Event()
    // <!-- 绑定once事件 -->
    myEvent.once('created', function () {
      console.log('created Event')
    })
    myEvent.once('mounted', function () {
      console.log('mounted Event')
    })
    // <!-- 绑定on事件 -->
    myEvent.on('update', function (params) {
      console.log('update Event', params)
    })
    myEvent.on('customEvent', function () {
      console.log('customEvent Event')
    })

    // 发射器函数
    function launch () {
      myEvent.emit('created')
      myEvent.emit('mounted')

      myEvent.emit('update', 'First Time')
      myEvent.emit('customEvent')

      myEvent.off('customEvent')

      myEvent.emit('update', 'The last time')
      myEvent.emit('customEvent')
      console.log('------')
      myEvent.emit('created')
      myEvent.emit('mounted')
    }
    // 执行发射器
    launch()
  </script>
</body>

</html>